Skip to content

Add phoenix-protocol (phUSD staking)#2682

Open
gititGoro wants to merge 3 commits into
DefiLlama:masterfrom
Behodler:add-phoenix-protocol
Open

Add phoenix-protocol (phUSD staking)#2682
gititGoro wants to merge 3 commits into
DefiLlama:masterfrom
Behodler:add-phoenix-protocol

Conversation

@gititGoro
Copy link
Copy Markdown

@gititGoro gititGoro commented May 15, 2026

Summary

Adds a yield adapter for the Phoenix Protocol phUSD staking contract on Ethereum mainnet, exposing a single pool searchable as phUSD.

Pool

  • Contract: 0x3984eBC84d45a889dDAc595d13dc0aC2E54819F4 (phUSD staking)
  • Symbol: phUSD
  • Project: phoenix-protocol
  • Chain: Ethereum

Stakers deposit phUSD and receive two emission-based rewards.

APY methodology

  • USDC reward — distributed via linear depletion. Spot rate rewardBalance / depletionDuration is annualized and divided by USD TVL.
  • phUSD reward — auto-minted to hit the contract's desiredAPYBps target. Computed directly as desiredAPYBps / 100 (currently 0; will activate when governance enables it).

apyReward is the sum of the two; apyBase is null (the staking action itself produces no organic yield).

Pricing

phUSD is priced from the Balancer V3 phUSD/sUSDS 50/50 weighted pool:

  1. Read pool balances via Vault getPoolTokens + getCurrentLiveBalances (both tokens 18-dec, no rate provider).
  2. Compute spot: phUsdPriceInSUsds = sUsdsBalance / phUsdBalance.
  3. Convert sUSDS → USDS via the sUSDS ERC4626 convertToAssets(1e18) live exchange rate.
  4. Treat USDS as $1.

Falls back to $1 peg with a warning if any of the on-chain reads fail.

USDC is hardcoded to $1.

Test plan

  • npm run test --adapter=phoenix-protocol — 11/11 passing.
  • Verified pool returned: 1 pool, symbol === 'phUSD', sane TVL (~$11.5k at time of writing).
  • All on-chain reads cross-checked against mainnet RPC.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for the Phoenix Protocol phUSD staking pool on DefiLlama yields, showing TVL and real-time APY that combines USDC and phUSD emission-based rewards with a safe pricing fallback to a $1 peg.
  • Documentation

    • Added documentation describing reward calculations, phUSD pricing derivation from Balancer pool data, and fallback behavior.

Review Change Stack

Single-pool adapter for the Phoenix Protocol phUSD staking contract on
Ethereum. Computes USDC reward APY from rewardBalance/depletionDuration
and reads the phUSD-emission APY directly from the contract's
desiredAPYBps target. Prices phUSD via the Balancer V3 phUSD/sUSDS pool
and the sUSDS ERC4626 conversion to USDS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f9c71e8-2eab-4a33-a945-2fd48f7a1f1f

📥 Commits

Reviewing files that changed from the base of the PR and between eba9023 and 1410c3e.

📒 Files selected for processing (2)
  • src/adaptors/phoenix-protocol/README.md
  • src/adaptors/phoenix-protocol/index.js
✅ Files skipped from review due to trivial changes (1)
  • src/adaptors/phoenix-protocol/README.md

📝 Walkthrough

Walkthrough

Adds a new Phoenix Protocol APY adapter that derives phUSD price from a Balancer V3 pool (with ERC4626 sUSDS rate and $1 fallback), reads PHLIMBO staking state on-chain, and computes USDC-based and phUSD-based APY components returning TVL and reward metadata.

Changes

Phoenix Protocol Staking Adapter

Layer / File(s) Summary
Adapter implementation and documentation
src/adaptors/phoenix-protocol/README.md, src/adaptors/phoenix-protocol/index.js
README documents phUSD reward and pricing formulas; index.js implements Balancer-based phUSD price derivation using sUSDS ERC4626 convertToAssets (with $1 fallback), concurrently reads PHLIMBO on-chain state (totalStaked, desiredAPYBps, rewardBalance, depletionDuration), computes TVL, USDC emission APY, phUSD desiredAPYBps component, and exports the pool result.

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers:

  • 0xkr3p

🐰 A phoenix rises from the staking pool,
With Balancer whispers and PHLIMBO rule,
phUSD and USDC twine in gentle cheer,
Rewards unfold — the rabbit hops near! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately and concisely summarizes the main change: adding a yield adapter for the Phoenix Protocol phUSD staking contract.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

The phoenix-protocol adapter exports pools:

Test Suites: 1 passed, 1 total
Tests: 11 passed, 11 total
Snapshots: 0 total
Time: 0.284 s
Ran all test suites.

Nb of pools: 1
 

Sample pools:
┌─────────┬───────────────────────────────────────────────────────┬────────────┬────────────────────┬─────────┬───────────────────┬─────────┬───────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────┬───────────┬─────────────────────────────────────┐
│ (index) │ pool                                                  │ chain      │ project            │ symbol  │ tvlUsd            │ apyBase │ apyReward         │ rewardTokens                                                                                   │ underlyingTokens                                 │ poolMeta  │ url                                 │
├─────────┼───────────────────────────────────────────────────────┼────────────┼────────────────────┼─────────┼───────────────────┼─────────┼───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────┼───────────┼─────────────────────────────────────┤
│ 0       │ '0x3984ebc84d45a889ddac595d13dc0ac2e54819f4-ethereum' │ 'Ethereum' │ 'phoenix-protocol' │ 'phUSD' │ 11537.63055818622 │ null    │ 6.308491807129091 │ [ '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', '0xf3B5B661b92B75C71fA5Aba8Fd95D7514A9CD605' ] │ [ '0xf3B5B661b92B75C71fA5Aba8Fd95D7514A9CD605' ] │ 'Staking' │ 'https://phusd.behodler.io/staking' │
└─────────┴───────────────────────────────────────────────────────┴────────────┴────────────────────┴─────────┴───────────────────┴─────────┴───────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────┴───────────┴─────────────────────────────────────┘

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/adaptors/phoenix-protocol/index.js (1)

51-59: ⚖️ Poor tradeoff

Consider BigInt arithmetic for precision.

Converting balances to Number (lines 51-52) may lose precision for very large pool balances. JavaScript Number has ~15-17 significant decimal digits, which could introduce small rounding errors for 18-decimal tokens with large supplies. For typical pool sizes this is acceptable, but using BigInt arithmetic would be more robust.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/phoenix-protocol/index.js` around lines 51 - 59, The code
currently converts balances and sharesToAssets to Number which can lose
precision; instead parse balances (balances[idxSusds], balances[idxPhusd]) and
sharesToAssets as BigInt, perform fixed-point arithmetic using a chosen SCALE
(e.g., BigInt(1e18)) to preserve 18-decimal precision: compute phUsdPriceInSUsds
= (sUsdsBalance * SCALE) / phUsdBalance and compute usdsPerSUsds =
(sharesToAssets * SCALE) / BigInt(1e18) (or equivalently keep shares scaled),
then multiply and rescale to produce the final result; update the expressions
that reference sUsdsBalance, phUsdBalance, sharesToAssets, phUsdPriceInSUsds,
and usdsPerSUsds to use BigInt arithmetic and convert the final value to Number
or string only at the return boundary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/adaptors/phoenix-protocol/index.js`:
- Around line 37-38: The calls to callView using getPoolTokensAbi and
getCurrentLiveBalancesAbi pass BALANCER_POOL as a bare value; update these
invocations so the third argument is an array containing BALANCER_POOL (e.g.,
callView(BALANCER_VAULT, getPoolTokensAbi, [BALANCER_POOL]) and similarly for
getCurrentLiveBalancesAbi) to match the ABI parameter format used elsewhere and
avoid SDK runtime errors.

---

Nitpick comments:
In `@src/adaptors/phoenix-protocol/index.js`:
- Around line 51-59: The code currently converts balances and sharesToAssets to
Number which can lose precision; instead parse balances (balances[idxSusds],
balances[idxPhusd]) and sharesToAssets as BigInt, perform fixed-point arithmetic
using a chosen SCALE (e.g., BigInt(1e18)) to preserve 18-decimal precision:
compute phUsdPriceInSUsds = (sUsdsBalance * SCALE) / phUsdBalance and compute
usdsPerSUsds = (sharesToAssets * SCALE) / BigInt(1e18) (or equivalently keep
shares scaled), then multiply and rescale to produce the final result; update
the expressions that reference sUsdsBalance, phUsdBalance, sharesToAssets,
phUsdPriceInSUsds, and usdsPerSUsds to use BigInt arithmetic and convert the
final value to Number or string only at the return boundary.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8c4801dc-2662-4d40-9e9d-072218b0caac

📥 Commits

Reviewing files that changed from the base of the PR and between b218cde and eba9023.

📒 Files selected for processing (2)
  • src/adaptors/phoenix-protocol/README.md
  • src/adaptors/phoenix-protocol/index.js

Comment thread src/adaptors/phoenix-protocol/index.js Outdated
Match the form already used by the convertToAssets call in the same
function. The SDK accepts both bare and array forms, but mixing them is
noisy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

The phoenix-protocol adapter exports pools:

Test Suites: 1 passed, 1 total
Tests: 11 passed, 11 total
Snapshots: 0 total
Time: 0.246 s
Ran all test suites.

Nb of pools: 1
 

Sample pools:
┌─────────┬───────────────────────────────────────────────────────┬────────────┬────────────────────┬─────────┬───────────────────┬─────────┬───────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────┬───────────┬─────────────────────────────────────┐
│ (index) │ pool                                                  │ chain      │ project            │ symbol  │ tvlUsd            │ apyBase │ apyReward         │ rewardTokens                                                                                   │ underlyingTokens                                 │ poolMeta  │ url                                 │
├─────────┼───────────────────────────────────────────────────────┼────────────┼────────────────────┼─────────┼───────────────────┼─────────┼───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────┼───────────┼─────────────────────────────────────┤
│ 0       │ '0x3984ebc84d45a889ddac595d13dc0ac2e54819f4-ethereum' │ 'Ethereum' │ 'phoenix-protocol' │ 'phUSD' │ 11537.63512248753 │ null    │ 6.308489311482701 │ [ '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', '0xf3B5B661b92B75C71fA5Aba8Fd95D7514A9CD605' ] │ [ '0xf3B5B661b92B75C71fA5Aba8Fd95D7514A9CD605' ] │ 'Staking' │ 'https://phusd.behodler.io/staking' │
└─────────┴───────────────────────────────────────────────────────┴────────────┴────────────────────┴─────────┴───────────────────┴─────────┴───────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────┴───────────┴─────────────────────────────────────┘

@gititGoro
Copy link
Copy Markdown
Author

Just checking in if there are any additional requirements before merge can happen

The phUSD staking contract was redeployed to
0x6084a02c2ac0127ddf1e617de257c61480a2aee0. Point the adapter at the
new address and document it in the README.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

The phoenix-protocol adapter exports pools:

Test Suites: 1 passed, 1 total
Tests: 11 passed, 11 total
Snapshots: 0 total
Time: 0.294 s
Ran all test suites.

Nb of pools: 1
 

Sample pools:
┌─────────┬───────────────────────────────────────────────────────┬────────────┬────────────────────┬─────────┬───────────────────┬─────────┬───────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────┬───────────┬─────────────────────────────────────┐
│ (index) │ pool                                                  │ chain      │ project            │ symbol  │ tvlUsd            │ apyBase │ apyReward         │ rewardTokens                                                                                   │ underlyingTokens                                 │ poolMeta  │ url                                 │
├─────────┼───────────────────────────────────────────────────────┼────────────┼────────────────────┼─────────┼───────────────────┼─────────┼───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────┼───────────┼─────────────────────────────────────┤
│ 0       │ '0x6084a02c2ac0127ddf1e617de257c61480a2aee0-ethereum' │ 'Ethereum' │ 'phoenix-protocol' │ 'phUSD' │ 12811.19997329351 │ null    │ 8.952333012448904 │ [ '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', '0xf3B5B661b92B75C71fA5Aba8Fd95D7514A9CD605' ] │ [ '0xf3B5B661b92B75C71fA5Aba8Fd95D7514A9CD605' ] │ 'Staking' │ 'https://phusd.behodler.io/staking' │
└─────────┴───────────────────────────────────────────────────────┴────────────┴────────────────────┴─────────┴───────────────────┴─────────┴───────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────┴───────────┴─────────────────────────────────────┘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant